package com.fast.develop.integration.orm;

import com.fast.develop.core.data.Page;
import com.fast.develop.core.data.Pageable;
import com.fast.develop.core.persistence.BatchObject;
import com.fast.develop.core.persistence.DomainModelManager;
import com.fast.develop.integration.exception.OrmIntegrationException;
import com.fast.develop.integration.orm.id.IdentifierSetter;
import com.fast.develop.integration.orm.id.MetaDomainModelsVisit;
import com.fast.develop.integration.orm.resolver.FieldTypeResolver;
import com.fast.develop.meta.base.MetaConfiguration;
import com.fast.develop.meta.dm.MetaDomainConstant;
import com.fast.develop.meta.dm.MetaDomainModel;
import org.hibernate.Session;

import javax.persistence.metamodel.EntityType;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 莫寅
 * @createTime 2022-06-23 03:18
 * @desc：
 */
public class DomainModelSessionManagerWrapper implements DomainModelManager {


    private FieldTypeResolver fileTypeResolver;
    private IdentifierSetter identifierSetter;
    private MetaDomainModelsVisit metaDomainModelsVisit;
    private Map<String, EntityType> entityTypes = new HashMap<>();
    private Session session;

    private Map<String, DomainModelManager> domainModelManagers = new HashMap<>();

    private static final String HIBERNATE_KEY = "hibernate";

    public DomainModelSessionManagerWrapper(MetaConfiguration metaConfiguration, Session session) {
        this.session = session;
        this.metaDomainModelsVisit = new MetaDomainModelsVisit(metaConfiguration);
        this.fileTypeResolver = new FieldTypeResolver(metaDomainModelsVisit);
        this.identifierSetter = new IdentifierSetter(metaDomainModelsVisit);
        this.entityTypes = session.getMetamodel().getEntities().stream().collect(Collectors.toMap(EntityType::getName, t -> t));

        initDomainModelManager();
    }

    private void initDomainModelManager(){
        DomainModelManager mapDomainModelSessionManager = new MapDomainModelSessionManager(
                session,
                fileTypeResolver,
                identifierSetter,
                metaDomainModelsVisit
        );


        DomainModelManager domainModelSessionManagerWrapper = new HibernateDomainModelSessionManager(
                session,
                entityTypes
        );
        domainModelManagers.put(MetaDomainConstant.TYPE, mapDomainModelSessionManager);
        domainModelManagers.put(HIBERNATE_KEY, domainModelSessionManagerWrapper);
    }


    /**
     * 是否元模型
     * @return
     */
    private boolean isMetaModel(String model){
        MetaDomainModel metaDomainModel = metaDomainModelsVisit.getMeta(model);
        if(metaDomainModel != null){
            return true;
        }else{
            return false;
        }
    }

    private DomainModelManager getDomainModelManager(String model){
        //是否元模型，不是则直接返回，不处理
        if(isMetaModel(model)){
            return domainModelManagers.get(MetaDomainConstant.TYPE);
        }else if(entityTypes.get(model) != null){
            return domainModelManagers.get(HIBERNATE_KEY);
        }

        throw new OrmIntegrationException("找不到元数据的持化久管理器！");
    }

    @Override
    public List list(String model) {
        return getDomainModelManager(model).list(model);
    }

    @Override
    public Page page(String model, Pageable pageable) {
        return getDomainModelManager(model).page(model, pageable);
    }

    @Override
    public Serializable create(String model, Object object) {
        return getDomainModelManager(model).create(model, object);
    }

    @Override
    public Object get(String model, Serializable serializable) {
        return getDomainModelManager(model).get(model, serializable);
    }

    @Override
    public void update(String model, Serializable id, Object object) {
        getDomainModelManager(model).update(model, id, object);
    }

    @Override
    public void delete(String model, Serializable id) {
        getDomainModelManager(model).delete(model, id);
    }

    @Override
    public BatchObject batch(String model, BatchObject batchObject) {
        return getDomainModelManager(model).batch(model, batchObject);
    }
}
